package com.piece.core.pay.client;

import com.piece.core.framework.support.response.AjaxResponse;
import com.piece.core.framework.util.validator.ValidatorUtil;
import com.piece.core.pay.dto.PayOrderUnifiedReqDTO;
import com.piece.core.pay.dto.PayRefundUnifiedReqDTO;
import lombok.extern.slf4j.Slf4j;

/**
 * 支付客户端的抽象类
 */
@Slf4j
public abstract class AbstractPayClient<Config extends PayClientConfig> implements PayClient {

    /**
     * 渠道编号
     */
    private final String channelId;

    /**
     * 渠道编码
     */
    private final String channelCode;

    /**
     * 错误码
     */
    protected AbstractPayResponseMapping codeMapping;

    /**
     * 支付配置
     */
    protected Config config;

    public AbstractPayClient(String channelId, String channelCode, Config config, AbstractPayResponseMapping codeMapping) {
        this.channelId = channelId;
        this.channelCode = channelCode;
        this.codeMapping = codeMapping;
        this.config = config;
    }

    /**
     * 初始化
     */
    public final void init() {
        doInit();
        log.info("[支付配置({}) 初始化完成]", config);
    }

    /**
     * 自定义初始化
     */
    protected abstract void doInit();

    public final void refresh(Config config) {
        // 判断是否更新
        if (config.equals(this.config)) {
            return;
        }
        log.info("[支付配置({})重新初始化]", config);
        this.config = config;
        // 初始化
        this.init();
    }

    protected Double calculateAmount(Long amount) {
        return amount / 100.0;
    }

    @Override
    public String getId() {
        return channelId + ":" + channelCode;
    }

    @Override
    public final AjaxResponse unifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
        ValidatorUtil.validate(reqDTO);
        try {
            return doUnifiedOrder(reqDTO);
        } catch (Throwable e) {
            return AjaxResponse.error(e.getMessage());
        }
    }

    /**
     * 下单实现接口
     */
    protected abstract AjaxResponse doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws Throwable;

    @Override
    public AjaxResponse unifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
        try {
            return doUnifiedRefund(reqDTO);
        }  catch (Throwable e) {
            log.error("[发起退款失败: ({})]", e);
            return AjaxResponse.error(e.getMessage());
        }
    }

    protected abstract AjaxResponse doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable;
}
